package cn.com.libertymutual.sp.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.beust.jcommander.internal.Lists;

import cn.com.libertymutual.core.util.BeanUtilExt;
import cn.com.libertymutual.core.util.Constants;
import cn.com.libertymutual.core.util.Current;
import cn.com.libertymutual.core.web.ServiceResult;
import cn.com.libertymutual.sp.bean.TbSpApprove;
import cn.com.libertymutual.sp.bean.TbSpArticle;
import cn.com.libertymutual.sp.bean.TbSpFlow;
import cn.com.libertymutual.sp.bean.TbSpFlowDetail;
import cn.com.libertymutual.sp.bean.TbSpProduct;
import cn.com.libertymutual.sp.bean.TbSysHotarea;
import cn.com.libertymutual.sp.dao.ApproveDao;
import cn.com.libertymutual.sp.dao.ArticleDao;
import cn.com.libertymutual.sp.dao.FlowDao;
import cn.com.libertymutual.sp.dao.FlowDetailDao;
import cn.com.libertymutual.sp.dao.ProductDao;
import cn.com.libertymutual.sp.dao.TbSysHotareaDao;
import cn.com.libertymutual.sp.dto.RateDto;
import cn.com.libertymutual.sp.service.api.ArticleService;
import cn.com.libertymutual.sp.service.api.InsureService;
import cn.com.libertymutual.sp.service.api.ShopService;
import cn.com.libertymutual.sys.dao.ISysRoleUserDao;

@Service("articleService")
public class ArticleServiceImpl implements ArticleService {

	private Logger log = LoggerFactory.getLogger(getClass());
	@Autowired
	private JdbcTemplate readJdbcTemplate;
	@Autowired
	private ArticleDao articleDao;
	@Autowired
	private ApproveDao approveDao;
	@Autowired
	private ProductDao productDao;
	@Autowired
	private TbSysHotareaDao hotareaDao;
	@Autowired
	private ISysRoleUserDao roleUserDao;
	@Autowired
	private FlowDao flowDao;
	@Autowired
	private FlowDetailDao flowDetailDao;
	@Autowired
	private ShopService shopService;
	@Autowired
	private InsureService insureService;

	@Override
	public ServiceResult allArticle(String productName, String riskCode, String name, String type, String status, Integer pageNumber,
			Integer pageSize) {
		ServiceResult sr = new ServiceResult();
		List<Order> orders = new ArrayList<Order>();
		orders.add(new Order(Direction.DESC, "status"));
		orders.add(new Order(Direction.ASC, "id"));
		String userId = Current.userId.get();
		Integer roleId = roleUserDao.findByUserid(userId).getRoleid();
		Sort sort = new Sort(orders);
		Page<TbSpArticle> page = articleDao.findAll(new Specification<TbSpArticle>() {
			public Predicate toPredicate(Root<TbSpArticle> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicate = new ArrayList<Predicate>();
				if (StringUtils.isNotEmpty(productName)) {
					log.info(productName);
					predicate.add(cb.like(root.get("productName").as(String.class), "%" + productName + "%"));
				}
				if (StringUtils.isNotEmpty(riskCode) && !"-1".equals(riskCode)) {
					log.info(riskCode);
					predicate.add(cb.equal(root.get("riskCode").as(String.class), riskCode));
				}
				if (StringUtils.isNotEmpty(name)) {
					log.info(name);
					predicate.add(cb.like(root.get("name").as(String.class), "%" + name + "%"));
				}
				if (StringUtils.isNotEmpty(type) && !"-1".equals(type)) {
					log.info(type);
					predicate.add(cb.equal(root.get("type").as(String.class), type));
				}

				if (StringUtils.isNotEmpty(status) && !"-1".equals(status)) {
					log.info(status);
					predicate.add(cb.equal(root.get("status").as(String.class), status));
				}

				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();
			}
		}, PageRequest.of(pageNumber - 1, pageSize, sort));

		if (null != page.getContent()) {
			List<TbSpArticle> list = page.getContent();
			for (TbSpArticle tsp : list) {
				// TbSpApprove tsa =
				// approveDao.findByTypeAndApproveId(Constants.ARTICLE_APPROVE,
				// tsp.getId().toString(), Constants.APPROVE_WAIT);
				TbSpApprove tsa = approveDao.findApproveFlow(Constants.ARTICLE_APPROVE, tsp.getId().toString(), Constants.APPROVE_WAIT,
						Constants.FLOW_ACTICLE);
				if (null != tsa) {
					tsp.setTbSpApprove(tsa);
					TbSpFlowDetail flowDetail = flowDetailDao.findByNoAndNode(tsa.getFlowNo(), tsa.getFlowNode());
					if (null != flowDetail && StringUtils.isNotBlank(flowDetail.getUserCode())) {// 用户审批
						String[] users = flowDetail.getUserCode().split("&");
						boolean b = Arrays.asList(users).contains(userId);
						if (b) {
							tsp.setApproveAuth("true");
						} else {
							tsp.setApproveAuth("false");
						}
					}
					if (null != flowDetail && StringUtils.isNotBlank(flowDetail.getRoleCode())) {// 角色审批
						String[] roles = flowDetail.getRoleCode().split("&");
						boolean b = Arrays.asList(roles).contains(roleId.toString());
						if (b) {
							tsp.setApproveAuth("true");
						} else {
							tsp.setApproveAuth("false");
						}
					}
				}
			}
		}
		sr.setResult(page);
		return sr;
	}

	@Override
	public ServiceResult articleList(String branchCode, String serchKey, String type, Integer pageNumber, Integer pageSize, String userCode) {
		ServiceResult sr = new ServiceResult();
		StringBuilder sql = new StringBuilder();
		List<Map<String, Object>> proList = null;
		TbSysHotarea hot = hotareaDao.findByAreaCode(branchCode);
		if (null != hot) {
			Integer sqlPageNumber = (pageNumber - 1) * pageSize;
			sql.append(
					"select ar.ID as id,ar.NAME as name,ar.TYPE as type,ar.RISKCODE as riskCode,ar.PRODUCT_ID as productId,ar.PRODUCT_NAME as productName,ar.SUMMARY_INFO as summaryInfo,ar.IMG_URL as imgUrl,ar.STATUS as status,pro.rate as rate from t_sp_article ar ");
			// 条件
			sql.append(
					" left join tb_sp_productconfig pro on pro.Product_id = ar.PRODUCT_ID where pro.status ='1' and ar.status in ('1','3')  and pro.Branch_code = ?");

			if (StringUtils.isNotEmpty(type) && "all".equals(type)) {
				if (StringUtils.isNotEmpty(serchKey)) {
					sql.append(" and ar.NAME like ? ");
					sql.append(" order by ar.CREATE_DATE desc,ar.ID asc LIMIT " + sqlPageNumber.toString() + "," + pageSize.toString());
					proList = readJdbcTemplate.queryForList(sql.toString(), new Object[] { hot.getBranchCode(), "%" + serchKey + "%" });
				} else {
					sql.append(" order by ar.CREATE_DATE desc,ar.ID asc LIMIT " + sqlPageNumber.toString() + "," + pageSize.toString());
					proList = readJdbcTemplate.queryForList(sql.toString(), new Object[] { hot.getBranchCode() });
				}
			} else {
				sql.append(" and ar.TYPE =? ");
				if (StringUtils.isNotEmpty(serchKey)) {
					sql.append(" and ar.NAME like ? ");
					sql.append(" order by ar.CREATE_DATE desc,ar.ID asc LIMIT " + sqlPageNumber.toString() + "," + pageSize.toString());
					proList = readJdbcTemplate.queryForList(sql.toString(), new Object[] { hot.getBranchCode(), type, "%" + serchKey + "%" });
				} else {
					sql.append(" order by ar.CREATE_DATE desc,ar.ID asc LIMIT " + sqlPageNumber.toString() + "," + pageSize.toString());
					proList = readJdbcTemplate.queryForList(sql.toString(), new Object[] { hot.getBranchCode(), type });
				}
			}
		}
		List<Map<String, Object>> newProList = Lists.newArrayList();
		RateDto rateDto = insureService.getLevelRate(userCode);
		String userTop = rateDto.getUserCode();
		Double levenRate = rateDto.getRate();
		Boolean isShowRate = shopService.isSetRate(userCode);
		if (proList != null) {
			for (Map<String, Object> map : proList) {
				Object rate = map.get("rate");
				if (isShowRate) {
					map.put("rate",
							shopService.getRate(Double.parseDouble(rate.toString()), userTop, map.get("productId").toString(), false) * levenRate);
				} else {
					map.put("rate", 0.0);
				}
				newProList.add(map);
			}
		}
		sr.setResult(newProList);
		return sr;
	}

	@Transactional(propagation = Propagation.REQUIRED) // 事务
	@Override
	public ServiceResult addOrUpdateArticle(TbSpArticle tbSpArticle) {
		String status = tbSpArticle.getStatus();
		log.info("请求参数------------>:{}", tbSpArticle.toString());
		ServiceResult sr = new ServiceResult();
		TbSpFlow flow = flowDao.findByType(Constants.FLOW_ACTICLE);
		if (null == flow) {
			sr.setFail();
			sr.setResult("请先配置文章审批流！");
			return sr;
		}
		List<TbSpFlowDetail> details = flowDetailDao.findByFlowNo(flow.getFlowNo());
		if (CollectionUtils.isNotEmpty(details) && details.size() <= 1) {
			sr.setFail();
			sr.setResult("请先配置文章审批流！");
			return sr;
		}
		if (null == tbSpArticle.getId()) {// 添加
			log.info("---------添加文章-----------");

			tbSpArticle.setCreateDate(new Date());
			tbSpArticle.setViews(0);
			tbSpArticle.setUserId(Current.userInfo.get().getUserId());
			tbSpArticle.setStatus(Constants.APPROVE_ADD);
			articleDao.save(tbSpArticle);
			tbSpArticle.setId(tbSpArticle.getId());
			TbSpArticle newtp = new TbSpArticle();
			try {
				BeanUtilExt.copyProperties(newtp, tbSpArticle);
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
			newtp.setStatus(status);
			String jsonstring = JSONObject.toJSONString(newtp, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
			log.info("-----jsonstring-----{}", jsonstring);
			// dbtbSpArticle.setStatus(status);
			TbSpApprove tsa = new TbSpApprove();
			tsa.setStatus(Constants.FALSE);
			tsa.setApproveId(tbSpArticle.getId().toString());
			tsa.setContent(jsonstring);
			tsa.setOriginalStatus(status);
			tsa.setApplyTime(new Date());
			tsa.setFlowNo(flow.getFlowNo());
			tsa.setFlowType(Constants.FLOW_ACTICLE);
			tsa.setFlowNode(flow.getLastFlowNode());
			tsa.setApplyUser(Current.userInfo.get().getUserId());
			tsa.setType(Constants.ARTICLE_APPROVE);
			approveDao.save(tsa);
			sr.setResult(tbSpArticle);
		} else {// 修改
			log.info("---------修改文章-----------");
			tbSpArticle.setModifyUser(Current.userInfo.get().getUserId());

			TbSpArticle dbtbSpArticle = articleDao.findById(tbSpArticle.getId()).get();
			TbSpArticle newtbSpArticle = new TbSpArticle();
			try {
				BeanUtilExt.copyProperties(newtbSpArticle, dbtbSpArticle);
			} catch (InvocationTargetException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			}
			if (!newtbSpArticle.differ(tbSpArticle)) {
				log.info("===============differ后不相同==================");
				try {
					TbSpArticle beantbSpPoster = (TbSpArticle) BeanUtilExt.differAbeanToBbean(newtbSpArticle, tbSpArticle);
					String jsonstring = JSONObject.toJSONString(beantbSpPoster, SerializerFeature.WriteMapNullValue,
							SerializerFeature.WriteNullStringAsEmpty);
					log.info("-----jsonstring-----{}", jsonstring);
					// 记录在审批表中
					TbSpApprove dbtsa = approveDao.findByTypeAndApproveId(Constants.ARTICLE_APPROVE, dbtbSpArticle.getId().toString(),
							Constants.APPROVE_WAIT);
					if (null != dbtsa) {
						dbtsa.setContent(jsonstring);
						dbtsa.setStatus(Constants.FALSE);
						dbtsa.setApproveId(dbtbSpArticle.getId().toString());
						dbtsa.setOriginalStatus(dbtbSpArticle.getStatus());
						dbtsa.setApplyTime(new Date());
						dbtsa.setFlowNo(flow.getFlowNo());
						dbtsa.setFlowType(Constants.FLOW_ACTICLE);
						dbtsa.setFlowNode(flow.getLastFlowNode());
						dbtsa.setApplyUser(Current.userInfo.get().getUserId());
						dbtsa.setType(Constants.ARTICLE_APPROVE);
						approveDao.save(dbtsa);
					} else {
						TbSpApprove tsa = new TbSpApprove();
						tsa.setStatus(Constants.FALSE);
						tsa.setApproveId(dbtbSpArticle.getId().toString());
						tsa.setContent(jsonstring);
						tsa.setOriginalStatus(dbtbSpArticle.getStatus());
						tsa.setApplyTime(new Date());
						tsa.setFlowNo(flow.getFlowNo());
						tsa.setFlowType(Constants.FLOW_ACTICLE);
						tsa.setFlowNode(flow.getLastFlowNode());
						tsa.setApplyUser(Current.userInfo.get().getUserId());
						tsa.setType(Constants.ARTICLE_APPROVE);
						approveDao.save(tsa);
					}
					if (Constants.TRUE.equals(dbtbSpArticle.getStatus())) {
						dbtbSpArticle.setStatus(Constants.APPROVE_UP_UPDATE);
					} else {
						dbtbSpArticle.setStatus(Constants.APPROVE_DOWN_UPDATE);
					}
					articleDao.save(dbtbSpArticle);
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			} else {
				log.info("===============differ相同==================");
				TbSpArticle savetbSpArticle = articleDao.save(tbSpArticle);
				sr.setResult(savetbSpArticle);
			}
		}

		return sr;
	}

	@Override
	public ServiceResult findArticle(Integer id) {
		ServiceResult sr = new ServiceResult();
		sr.setResult(articleDao.findById(id).get());
		return sr;
	}

	@Override
	public ServiceResult findSoftPaper(Integer id) {
		ServiceResult sr = new ServiceResult();
		if (id != null) {
			TbSpArticle findArt = articleDao.findById(id).get();
			if (findArt != null) {
				TbSpProduct pro = productDao.findByIdYes(findArt.getProductId());
				TbSpArticle tbSpArt = new TbSpArticle();
				tbSpArt.setDesc(pro.getDescrition());
				tbSpArt.setMinPrice(pro.getMinPrice());
				tbSpArt.setName(findArt.getName());
				tbSpArt.setRiskCode(findArt.getRiskCode());
				tbSpArt.setProductId(findArt.getProductId());
				tbSpArt.setProductName(findArt.getProductName());
				tbSpArt.setSummaryInfo(findArt.getSummaryInfo());
				tbSpArt.setContent(findArt.getContent());
				tbSpArt.setImgUrl(findArt.getImgUrl());
				tbSpArt.setViews(findArt.getViews());
				tbSpArt.setId(id);
				if (findArt.getViews() != null) {
					Integer views = findArt.getViews();
					views++;
					findArt.setViews(views);
				} else {
					findArt.setViews(0);
				}
				articleDao.save(findArt);
				sr.setResult(tbSpArt);
			} else {
				sr.setFail();
			}
		} else {
			sr.setFail();
		}
		return sr;
	}

}
